/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.customize.enums.AbnormalEnum;
import com.pig4cloud.pigx.common.customize.enums.CommonDictEnum;
import com.pig4cloud.pigx.common.customize.exception.DuckweedException;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.redis.constants.RedisKeyEnum;
import com.pig4cloud.pigx.common.customize.redis.utils.RedisUtils;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.id.IdWorker;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.user.constant.WalletConstant;
import com.pig4cloud.pigx.user.dto.AppFuelReceivePageDTO;
import com.pig4cloud.pigx.user.dto.FuelReceiveDividendsPageDTO;
import com.pig4cloud.pigx.user.entity.*;
import com.pig4cloud.pigx.user.enums.*;
import com.pig4cloud.pigx.user.mapper.FuelReceiveDividendsMapper;
import com.pig4cloud.pigx.user.service.*;
import com.pig4cloud.pigx.user.vo.AdminPageDemoVO;
import com.pig4cloud.pigx.user.vo.LoginUserFuelReceiveVO;
import com.pig4cloud.pigx.user.vo.MarginBalanceVO;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 燃料分红明细
 *
 * @author pigx code generator
 * @date 2022-11-24 17:38:53
 */
@AllArgsConstructor
@Service
public class FuelReceiveDividendsServiceImpl extends ServiceImpl<FuelReceiveDividendsMapper, FuelReceiveDividends> implements FuelReceiveDividendsService {

	private final MysqlUtil mysqlUtil;

	private final CapitalAccountService capitalAccountService;

	private final IdWorker idWorker;

	private final RechargeRecordService recordService;

	private final RedisUtils redisUtils;
	private final CurrencyService currencyService;

	@Override
	public R<Page<LoginUserFuelReceiveVO>> getAppPage(AppFuelReceivePageDTO dto) {
		try {
			PigxUser user = SecurityUtil.getLoginUser();
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			Page<FuelReceiveDividends> page = baseMapper.selectPage(new Page<FuelReceiveDividends>() {{
				setCurrent(dto.getCurrent());
				setSize(dto.getSize());
			}}, new QueryWrapper<FuelReceiveDividends>() {{
				if (dto.getIsAllChild().equals(CommonDictEnum.YesOrNo.YES.getValue())) {
					List<User> list = new ArrayList<>();
					getAllChild(list,user.getId());
					List<Long> longs = list.stream().map(User::getId).collect(Collectors.toList());
					longs.add(user.getId());
					in("user_id",longs);
				} else {
					eq("user_id", user.getId());
				}
				if (dto.getType() != null) {
					ge("type", dto.getType());
				}
				if (dto.getStartTime() != null) {
					ge("create_time", dto.getStartTime());
				}
				if (dto.getEndTime() != null) {
					le("create_time", dto.getEndTime());
				}
				select(
						"id",
						"order_id",
						"fuel_quantity",
						"fuel_proportion",
						"type",
						"create_time",
						"is_success",
						"fuel_consume_id",
						"(select user_id from transfer_detailed where id = fuel_consume_id) 'userId'"
				);
				orderByDesc("create_time");
			}});
			Page<LoginUserFuelReceiveVO> voPage = new Page<>();
			BeanUtils.copyProperties(page,voPage);
			List<LoginUserFuelReceiveVO> voList = new ArrayList<>();
			for (FuelReceiveDividends record : page.getRecords()) {
				LoginUserFuelReceiveVO vo = new LoginUserFuelReceiveVO();
				BeanUtils.copyProperties(record,vo);
				vo.setType(FuelReceiveDividendsEnums.Type.findName(vo.getType()));
				if (vo.getFuelProportion() != null) {
					vo.setFuelProportion(vo.getFuelProportion().multiply(new BigDecimal("100")));
				}
				vo.setFuelQuantity(vo.getFuelQuantity().setScale(6, RoundingMode.DOWN));
				vo.setIsSuccess(CommonDictEnum.YesOrNo.findName(vo.getIsSuccess()));
				voList.add(vo);
			}
			voPage.setRecords(voList);
			return R.ok(voPage);
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 递归获取所有子集
	 * @param list list
	 * @param id 父级id
	 */
	public void getAllChild(List<User> list,Long id) {
		List<User> userList = new User().selectList(new QueryWrapper<User>() {{
			eq("parent_id", id);
		}});
		if (userList.size() > 0) {
			list.addAll(userList);
			for (User user : userList) {
				getAllChild(list,user.getId());
			}
		}
	}

	@Override
	public R<AdminPageDemoVO<FuelReceiveDividends>> pageList(FuelReceiveDividendsPageDTO dto) {
		try {
			QueryWrapper<FuelReceiveDividends> wrapper = new QueryWrapper<FuelReceiveDividends>() {{
				if (dto.getUserId() != null) {
					like("user_id", dto.getUserId());
				}
				if (dto.getType() != null && !dto.getType().isEmpty()) {
					eq("type", dto.getType());
				} else {
					ne("type", FuelReceiveDividendsEnums.Type.REWARD_RECHARGE.getValue());
				}
				if (dto.getStartTime() != null) {
					ge("create_time", dto.getStartTime());
				}
				if (dto.getEndTime() != null) {
					le("create_time", dto.getEndTime());
				}
				last("ORDER BY create_time DESC,fuel_quantity DESC");
			}};
			Page<FuelReceiveDividends> page = baseMapper.selectPage(new Page<FuelReceiveDividends>() {{
				setCurrent(dto.getCurrent());
				setSize(dto.getSize());
			}},wrapper );
			for (FuelReceiveDividends record : page.getRecords()) {
				record.setType(FuelReceiveDividendsEnums.Type.findName(record.getType()));
				record.setIsSuccess(CommonDictEnum.YesOrNo.findName(record.getIsSuccess()));
				record.setFuelProportion(record.getFuelProportion().multiply(new BigDecimal("100")));
				record.setFuelQuantity(record.getFuelQuantity().setScale(6,RoundingMode.DOWN).stripTrailingZeros());
			}
			FuelReceiveDividends selectOne = baseMapper.selectOne(wrapper.select(
					"sum(fuel_quantity) 'fuelQuantity'," +
							"sum(fuel_proportion) 'fuelProportion'"
			));
			if (selectOne != null && selectOne.getFuelQuantity() != null) {
				selectOne.setFuelQuantity(selectOne.getFuelQuantity().setScale(6,RoundingMode.DOWN).stripTrailingZeros());
			}
			return R.ok(new AdminPageDemoVO<FuelReceiveDividends>(){{
				setPage(page);
				setStatistics(selectOne);
			}});
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public void addList(List<FuelReceiveDividends> dividendsList) {
		for (FuelReceiveDividends dividends : dividendsList) {
			try {
				// 保证金不做即时处理
				if ( dividends.getType().equals(FuelReceiveDividendsEnums.Type.MARGIN.getValue()) ||
						dividends.getType().equals(FuelReceiveDividendsEnums.Type.NET_INCOME.getValue())
				) {
					continue;
				}
				if (dividends.getUserId() != null) {
					// 修改资金账户余额
					capitalAccountService.updateBalance(dividends.getUserId(), WalletConstant.USDT, dividends.getFuelQuantity(), true,true);
					// 新增充值记录
					RechargeRecord record = new RechargeRecord();
					record.setId(idWorker.nextId());
					record.setUserId(dividends.getUserId());
					record.setQuantity(dividends.getFuelQuantity());
					record.setCurrency(WalletConstant.USDT);
					record.setType(dividends.getType());
					record.setState(RechargeRecordEnum.Status.SUCCESS.getValue());
					recordService.save(record);
				}
				// 燃料分配成功
				dividends.setIsSuccess(CommonDictEnum.YesOrNo.YES.getValue());
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				baseMapper.insert(dividends);
			}
		}
	}

	/**
	 * 获取平台保险金
	 * @return r
	 */
	@Override
	public R<MarginBalanceVO> getMarginBalance() {
		try {
			MarginBalanceVO vo = new MarginBalanceVO();
			// 获取保险金地址
			TimingConfig config = redisUtils.getPersistentCache(RedisKeyEnum.TIMING_CONFIG, TimingConfigEnums.Type.TRON_MARGIN.getValue(), TimingConfig.class);
			String marginAddress = config.getAddress() == null ? "" : config.getAddress();
			vo.setTronAddress(marginAddress);
			TimingConfig bscConfig = redisUtils.getPersistentCache(RedisKeyEnum.TIMING_CONFIG, TimingConfigEnums.Type.BSC_MARGIN.getValue(), TimingConfig.class);
			String bscAddress = bscConfig.getAddress() == null ? "" : bscConfig.getAddress();
			vo.setBscAddress(bscAddress);
			FuelReceiveDividends dividends = new FuelReceiveDividends().selectOne(new QueryWrapper<FuelReceiveDividends>() {{
				eq("type", FuelReceiveDividendsEnums.Type.MARGIN.getValue());
				select("sum(fuel_quantity) fuelQuantity");
			}});
			vo.setMarginBalance(dividends == null || dividends.getFuelQuantity() == null ? BigDecimal.ZERO : dividends.getFuelQuantity());
			return R.ok(vo);
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}
}
